package com.bjsxt;
/**生产者与消费者的线程并发协作模式*/


//以面包为例，定义面包类
class Bread{
    private int id;//面包个数
    public Bread(int id){ //构造方法，实例化时传入参数
        this.id=id;
    }
    public int getId(){
        return this.id;
    }
}
/*定义生产者和消费者的缓冲区类*/
//不用继承Thread类
class SyncSlack02{
    /*定义面包类的盒子*/
    private  Bread[] breads = new Bread[10];
    private int index;//盒子有索引
    /*放面包  要用synchronized 因为存放与取要有顺序
    * 参数传入面包类*/
    public synchronized void push(Bread bread){
        //当放满时等待
        while (this.index==this.breads.length){
            //启动wait()  这是来源于Object类
            //该方法必须要在synchronized 块中调用
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        //当盒子满子，pUsh方法在等待，唤醒同一个对象锁的线程
        //唤醒取面包者线程  该方法必须要在synchronized 块中调用
        this.notify();

        //做好的面包放进容器里
        this.breads[this.index] =bread;
        this.index++;
    }
    /*取面包,需要返回面包*/
    public synchronized Bread pop(){
        //当取完面包时，等待生产者生产
        while (this.index==0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //当取完面包时，放面包的线程处于阻塞状态时，唤醒放面包线程
        this.notify();
        this.index--;
        return this.breads[this.index];

    }
}
/*定义生产者线程类*/
class ShengChan02 extends Thread {
    //将缓冲区的对象传入来
    private SyncSlack02 ss2;
    //实例化时传入参数
    public ShengChan02(SyncSlack02 ss2) {
        this.ss2 = ss2;
    }

    @Override
    public void run() {
        //遍历每一个面包
        for (int i = 0; i < 10; i++) {
            System.out.println("生产面包：" + i);
            Bread bread = new Bread(i); //实现面包类
            this.ss2.push(bread);
        }
    }
}
//消费者线程
class XiaoFei02 extends Thread{
        private SyncSlack02 ss2;
        public XiaoFei02(SyncSlack02 ss2){
            this.ss2=ss2;
        }
        @Override
        public void run() {
            for (int i=0;i<10;i++){
                //缓冲区面包取面包的方法，返回的面包就是消费者购买的面包
                Bread bread = this.ss2.pop();
                System.out.println("取走面包："+i);

            }
        }

}
public class ProduceThread02 {
    public static void main(String[] args) {
        //实例化缓冲区
        SyncSlack02 ss2 = new SyncSlack02();
        //启动线程
        new ShengChan02(ss2).start();
        new XiaoFei02(ss2).start();
    }
}
